import java.net.*;
import java.util.Vector;
import java.io.*;

//This class initiates the MatrixCalculator, opens the socket and listens for client connection, 
//each client will get a different thread to attend the corresponding connection. 
public class MatrixCalculatorSecondImplementation {
	//In this request queue the different connections are stored, so a connection consumer will get them out to attend them. 
	//This ensures that no connection is lost
	public static Vector <Socket> requestQueue= new Vector <Socket> ();
	public static void main (String args[]) {
		try{
			int serverPort = 7896; // the server port
		
			ServerSocket listenSocket = new ServerSocket(serverPort);
			
			while(true) {
				Socket clientSocket = listenSocket.accept();
			    //Here you can note the "per connection" architecture, 
				//each connection gets a worker thread that will attend each of the petitions of the client
				ConnectionWorker c = new ConnectionWorker(clientSocket);
			}
		} catch(IOException e) {System.out.println("Listen socket:"+e.getMessage());}
	}
}


//The connectionWorker will attend the client petitions, this will create a operation worker to parse the client message 
//to know the matrix size and the operation.
//This worker will run the operation as well
class ConnectionWorker extends Thread {
	DataInputStream in;
	DataOutputStream out;
	Socket clientSocket;

	public ConnectionWorker (Socket aClientSocket) {
		try {
			clientSocket = aClientSocket;
			in = new DataInputStream( clientSocket.getInputStream());
			out =new DataOutputStream( clientSocket.getOutputStream());
			this.start();
		} catch(IOException e) {System.out.println("Connection:"+e.getMessage());}
	}
	public void run(){
		try {			                 // an echo server
			String data="";
			while (true){
				data = in.readUTF();	 // read a line of data from the stream
				//This class will do the parsing and operation 
				ThreadPerConnection Worker = new ThreadPerConnection(data);
				//this is not really a thread only a worker class that will do the parsing,  matrix creation and operation
				String reply=Worker.run();
				
				out.writeBytes(reply);
				out.flush();
			}
			
		}catch (EOFException e){System.out.println("EOF:"+e.getMessage());
		} catch(IOException e) {System.out.println("readline:"+e.getMessage());
		} finally{ try {clientSocket.close();}catch (IOException e){/*close failed*/}}
		

	}
}

class ConnectionsHandle extends Thread {
	
	public ConnectionsHandle (){
		this.start();
	}
	public void run(){
		while(true){
			if(!MatrixCalculatorSecondImplementation.requestQueue.isEmpty()){
				ConnectionWorker c = new ConnectionWorker(MatrixCalculatorSecondImplementation.requestQueue.get(0));
				MatrixCalculatorSecondImplementation.requestQueue.remove(0);
				if(c.isAlive()){
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			}
			
		}
	}
}

